package controllers;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

import org.hibernate.engine.Status;

import models.*;
import play.cache.Cache;
import play.data.validation.Equals;
import play.data.validation.Required;
import play.mvc.*;

import models.RegisteredUser.*;
import models.RegisteredUser;
import models.Relation;
import models.Topic;
import models.Tutorial;
import models.EditRequest;
import play.*;
import play.db.jpa.*;
import play.db.jpa.GenericModel.JPAQuery;

import java.util.*;
import javax.management.Query;

import java.awt.Window;
import java.awt.event.WindowEvent;

import java.awt.image.renderable.RenderableImage;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Statement;
//import play.db.jpa.JPABase.em
import play.db.jpa.*;

//import java.sql.ResultSet;
//import java.sql.SQLException;
import java.sql.*;

@CRUD.For(models.Tutorial.class)
/**
 * this annotation calls crud module
 * 
 * @author Renad
 */
public class Tutorials extends Controller {

	/**
	 * This method takes the id of the topic, and renders the createTutorial
	 * page with the topic to be used.
	 * 
	 * @author Rana Amr
	 * @param topicId
	 */
	public static void createTutorial(long topicId) {
		Topic topic = Topic.findById(topicId);
		render(topic);
	}
	public static void tempcreatetut(long topicId) {
		Topic topic = Topic.findById(topicId);
		render(topic);
	}

	/**
	 * This method takes the ID of a tutorial and renders the the tutorial page
	 * with the content of that tutorial.
	 * 
	 * @author Rana Amr
	 * @param long tutId
	 */

	public static void tutorialPage(long tutId) {
		Tutorial tutorial = Tutorial.findById(tutId);
		render(tutorial);
	}

	/**
	 * This method creates a new Tutorial. It takes the attributes and checks
	 * that they are not null, and then creates a new tutorial. Then it renders
	 * the relation page.
	 * 
	 * @author Rana amr : responsible for the content, experience level
	 * @author Yasmin Gamal : responsible for Title,Topic and key Words
	 * @param : TopicId, title, content, words, Exp
	 */

	public static void createNewTutorial(
			String topicId,
			@Required(message = "You need to Enter the Title") String title,
			@Required(message = "You need to Enter the Content") String content,
			String summary,
			@Required(message = "You need to Enter the Related Words") String words,
			String Exp) {

		if (Exp.equals("Select")) {
			renderText("You need to choose an Experience Level");
		}
		long topId = Long.parseLong(topicId);
		Topic topic = Topic.findById(topId);

		if (validation.hasErrors()) {
			params.flash();
			validation.keep();
			createTutorial(topId);
		} else {
			long uid = Long.parseLong(session.get("RegisteredUserId"));
			RegisteredUser user = RegisteredUser.findById(uid);

			if (checkTitle(title)) {
				renderText("There already a Title with that Name");
			}

			if (checkTitleWords(title)) {
				renderText("Opps something went wrong, "
						+ "Make sure you entered only letter or numbers in the Title ");
			}
			if (checkKeyWords(words)) {
				renderText("Opps something went wrong, Make sure you entered only letter or numbers in the key words"
						+ "And You have to enter the words with only commas in between");
			}
			models.Tutorial newTutorial = new models.Tutorial(title, topic,
					content,summary, words, Exp, user);
			newTutorial.save();
			topic.addTutorial(newTutorial);

			LogRecord.createLog("Created a new tutorial :" + newTutorial.Title,
					user);

			editVersion e = new editVersion(newTutorial.id, title,/* topic, */
			content, words, Exp);
			e.save();
			newTutorial.edits.add(e);

			session.put("TutorialID", newTutorial.id);
			user.addPoints();
			user.addTutorial(newTutorial.getId());
			user.isCreator = true;
			user.save();

			relation(newTutorial.id);
		}
	}
	/**
	 * This method is for the autocomplete tags part. It uses the
	 * term being entered along with the topic the tutorial the user
	 * is at and renders the list of similar tags.
	 * 
	 * @author Aya Sakr 
	 * @param term: the string being entered at the moment in the input field
	 * topicId: the id of the topic that is the tutorial being created in
	 */
	public static void autocomplete(String term, long topicId){
    	List<Tutorial> tutorialsInCurrentTopic = Tutorial.find("Ttopic=?", topicId ).fetch();
    	List<String> myTags = new ArrayList<String>();
    	for(int i = 0; i<tutorialsInCurrentTopic.size(); i++){
    		String theTags = tutorialsInCurrentTopic.get(i).getStringofwords();
    		String[] splitted = theTags.split(",");
    		for(int j = 0; j<splitted.length; j++)
    			myTags.add(splitted[j]);
    	}
    	List<String> similar = new ArrayList<String>();
    	for(int i = 0; i<myTags.size(); i++){
    		if (myTags.get(i).toLowerCase().startsWith(term.toLowerCase())) {
   	         similar.add(myTags.get(i));
   	      }
    	}
    	renderJSON(similar);
    }
	public static List<String> locations() {
		   final List<String> result = new ArrayList<String>();
		   final String[] timeZones = TimeZone.getAvailableIDs();
		   for (int i = 0; i < timeZones.length; i++) {
		      final String[] parts = timeZones[i].split("/");
		      if (parts.length == 2 && parts[1].matches("[A-Za-z_]+")) {
		         final String location = parts[1].replaceAll("_", " ");
		         result.add(location);
		      }
		   }
		   Collections.sort(result);
		   System.out.println("ah");
		   return result;
	}
	public static int AUTOCOMPLETE_MAX = 10;
	 
	public static void autocompleteLabel(final String term) {
		System.out.println("I am here");
	   final List<String> response = new ArrayList<String>();
	   for (String label : locations()) {
	      if (label.toLowerCase().startsWith(term.toLowerCase())) {
	         response.add(label);
	      }
	      if (response.size() == AUTOCOMPLETE_MAX) {
	         break;
	      }
	   }
	   renderJSON(response);
	}


	/**
	 * checks if the there is already a title with that name
	 * 
	 * @param Title
	 * @return
	 * @author Yasmin G
	 */
	public static boolean checkTitle(String Title) {
		List<Tutorial> Tutorials = Tutorial.find("Title=?", Title).fetch();

		if (!Tutorials.isEmpty()) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * this method checks if the creator doesn't enter any invalid characters in
	 * title if so it return a message that he/she should only enter letters and
	 * numbers
	 * 
	 * @author Yasmin Gamal
	 * @param words
	 * @return
	 */
	public static boolean checkTitleWords(String words) {
		boolean flag = false;
		for (int i = 0; i <= words.length() - 1; i++) {
			String temp = words.substring(i, i + 1);
			char c = temp.charAt(0);
			switch (c) {
			case '+':
			case ')':
			case '"':
			case '=':
			case ';':
			case ',':
				flag = true;
				break;
			}
			if (flag) {
				return true;
			}
		}
		if (flag) {
			return true;
		}
		for (int i = 0; i <= words.length() - 1; i++) {
			String temp = words.substring(i, i + 1);
			char c = temp.charAt(0);
			switch (c) {
			case '{':
			case '[':
			case ']':
			case '%':
			case '@':
			case '#':
				flag = true;
				break;
			}
			if (flag) {
				return true;
			}
		}
		if (flag) {
			return true;
		}
		for (int i = 0; i <= words.length() - 1; i++) {
			String temp = words.substring(i, i + 1);
			char c = temp.charAt(0);
			switch (c) {
			case '$':
			case '~':
			case '>':
			case '*':
			case '(':
			case '^':
				flag = true;
				break;
			}

			if (flag) {
				return true;
			}
		}
		for (int i = 0; i <= words.length() - 1; i++) {
			String temp = words.substring(i, i + 1);
			char c = temp.charAt(0);
			switch (c) {
			case '!':
			case '|':
			case '.':
				flag = true;
				break;
			}
			if (flag) {
				return true;
			}
		}
		return flag;
	}

	/**
	 * this method checks if the creator doesn't enter any invalid characters if
	 * so it return a message that he/she should only enter letters and numbers
	 * 
	 * @author Yasmin Gamal
	 * @param words
	 * @return
	 */
	public static boolean checkKeyWords(String words) {
		boolean flag = false;
		for (int i = 0; i <= words.length() - 1; i++) {
			String temp = words.substring(i, i + 1);
			char c = temp.charAt(0);
			switch (c) {
			case '+':
			case ')':
			case '"':
			case '=':
			case ';':
			case ' ':
				flag = true;
				break;
			}
			if (flag) {
				return true;
			}
		}
		if (flag) {
			return true;
		}
		for (int i = 0; i <= words.length() - 1; i++) {
			String temp = words.substring(i, i + 1);
			char c = temp.charAt(0);
			switch (c) {
			case '{':
			case '[':
			case ']':
			case '%':
			case '@':
			case '#':
				flag = true;
				break;
			}
			if (flag) {
				return true;
			}
		}
		if (flag) {
			return true;
		}
		for (int i = 0; i <= words.length() - 1; i++) {
			String temp = words.substring(i, i + 1);
			char c = temp.charAt(0);
			switch (c) {
			case '$':
			case '~':
			case '>':
			case '*':
			case '(':
			case '^':
				flag = true;
				break;
			}

			if (flag) {
				return true;
			}
		}
		for (int i = 0; i <= words.length() - 1; i++) {
			String temp = words.substring(i, i + 1);
			char c = temp.charAt(0);
			switch (c) {
			case '!':
			case '|':
			case '.':
				flag = true;
				break;
			}
			if (flag) {
				return true;
			}
		}
		return flag;
	}

	/**
	 * 
	 * * This method is for the relation page in order to let the creator link
	 * the created tutorial to another tutorial chosen from the drop down list
	 * taken two parameter which are the title of the tutorial he/she wants to
	 * relate to and the type of the relation if similar,replace,required to,
	 * required for,part of.
	 * 
	 * @author Yasmin Gamal
	 * 
	 * @param String
	 *            title which is the title
	 * @param String
	 *            relation which is similar, required to , required for or
	 *            replace.
	 */

	public static void relationPage(String TutorialId, String title,
			String relation) {
		long currentTutorialId = Long.parseLong(TutorialId);
		Tutorial tut = Tutorial.findById(currentTutorialId);
		String tutorialName = tut.Title;
		Relation r = new Relation(tutorialName, title, relation);
		r.save();
		Application.updates();

	}

	/**
	 * This method renders the Relation.html page and displays the Tutorial
	 * titles
	 * 
	 * @Yasmin Gamal
	 * 
	 * @param no
	 *            parameters
	 */
	public static void relation(long tutId) {
		Tutorial currentTut = Tutorial.findById(tutId);
		String currentTitle = currentTut.Title;
		List<Relation> relation = Relation
				.find("TutorialTitle=?", currentTitle).fetch();

		long uId = Long.parseLong(session.get("RegisteredUserId"));
		RegisteredUser user = RegisteredUser.findById(uId);
		models.Tutorial tutorial = models.Tutorial.findById(tutId);
		if (user.isContributor || user.id == tutorial.creator.id) {
			if (relation.isEmpty()) {
				List<Tutorial> Tutorials = Tutorial.find("id!=?", tutId)
						.fetch();
				render(currentTut, Tutorials);
			} else {
				renderText("The Tutorial is already related");
			}
		} else {
			renderText("You are not authorized to create a relation");
		}
	}

	/***
	 * This method is for deleting relations between tutorials
	 * 
	 * @author Nourhan Elmalahy @ @param relationID
	 */

	public static void deleteRelations(long tutorialId) {
		Tutorial t = Tutorial.findById(tutorialId);
		String title = t.Title;
		Relation relation = Relation.find("tutorialTitle=?", title).first();
		relation.delete();
		renderText("You have deleted the relation successfully!");
	}

	/***
	 * This method is for changing the mode of the tutorial to publish mode
	 * 
	 * @author Nourhan Elmalahy
	 * @param tutId
	 */
	public static void publishTutorial(long tutId) {
		Tutorial tut = Tutorial.findById(tutId);
		if (((tut.isReady() == true) && ((tut.status.equals("draft"))||(tut.status.equals("hide"))))) {
			tut.publishTutorial();
			tut.save();
			Application.updates();
		} else {
			renderText("The tutorial needs to be accepted by the reviewer or it's already in the publish mode");
		}
	}

	/***
	 * This method is for changing the status of the tutorial into hide
	 * 
	 * @author Nourhan Elmalahy
	 * @param tutId
	 */
	public static void hideTutorial(long tutId) {
		Tutorial tut = Tutorial.findById(tutId);
		tut.hideTutorial();
		tut.save();
		Application.updates();
	}

	/***
	 * end --> Nourhan Elmalahy
	 */

	// Start ---> Omnia
	/**
	 * This Method is to like a tutorial, it checks if the logged-in user has
	 * liked this tutorial before, If no, it renders that he already likes it.
	 * If yes, it increments the likeCount of the tutorial by one, and add the
	 * tutorial to the like list of the user.
	 * 
	 * @return if user not logged-in --> return "you are not logged in" if the
	 *         user liked this tutorial before --> return
	 *         "you have liked this tut before" else a confirmation message
	 *         should appear
	 * 
	 * @param tutorialId
	 *            ID of the opened Tutorial Story [C3][S11]
	 * @author Omnia
	 */

	public static void likeTutorial(long tutorialId) {
		if (session.get("RegisteredUserId") != null) {
			{
				long userId = Long.parseLong(session.get("RegisteredUserId"));
				RegisteredUser user = RegisteredUser.findById(userId);
				Tutorial tutorial = Tutorial.findById(tutorialId);
				if (!(user.likeList.contains(tutorial)))
				// to check that this user didn't like this tutorial before
				{
					tutorial.likeCount++;
					tutorial.save();
					user.likeList.add(tutorial);
					user.save();
					if (userId != tutorial.creator.id)
						new Notification(userId, tutorial.creator.id,
								tutorialId, 1).save();
					renderText("You have successfully liked this Tutorial ");
				}
			}
			renderText("Seems like you have liked this tutorial before!!");
		} else {
			renderText("you are not logged-in please log in");
		}
	}

	/**
	 * this method is to delete this comments on a specific tutorial, the
	 * deleter could be the comment creator, the creator of the tutorial or the
	 * contributors to this tutorial
	 * 
	 * @return if user not logged-in --> return "you are not logged in" if he is
	 *         not allowed to delete --> "you are not allowed to delete"
	 * @param commentID
	 *            ID of the comment to be deleted
	 * @author Omnia
	 */
	public static void deleteComment(long commentID) {
		if (session.get("RegisteredUserId") != null) {
			long userId = Long.parseLong(session.get("RegisteredUserId"));
			Comment comment = Comment.findById(commentID);
			RegisteredUser user = RegisteredUser.findById(userId);
			long tutorialId = comment.tutId;
			Tutorial tutorial = Tutorial.findById(tutorialId);
			if ((comment.commentorId == userId)
					|| (tutorial.contributorsList.contains(user))
					|| tutorial.creator.equals(user)) {
				comment.delete();
				if (comment.isPrivate)
					Tutorials.viewPrivateComments(tutorialId);
				Tutorials.viewPublicComments(tutorialId);
			} else {
				renderText("you are not allowed to delete this comment");
			}
		} else {
			renderText("you are not logged-in please log in");
		}
	}

	/**
	 * this method to enable a registered user to request to be a contributer in
	 * a tutorial, the request is sent to the creator(owner) of the tutorial It
	 * checks if the user is NOT CONTRIBUTOR and NOT CREATOR of this tutorial
	 * and have not sent a request and has pending status. if all true: it
	 * creates a new Request
	 * 
	 * @return if user not logged-in --> return "you are not logged in" if he is
	 *         creator of tut --> "you are the creator of the tut" if he is
	 *         already a contributor --> "you are a contributor" else a
	 *         confirmation message appears
	 * 
	 * @param tutorialId
	 *            ID of the opened Tutorial Story [C3][S9]
	 * 
	 * @author Omnia
	 */
	public static void requestToContribute(long tutorialId) {
		if (session.get("RegisteredUserId") != null) {
			long uid = Long.parseLong(session.get("RegisteredUserId"));
			RegisteredUser user = RegisteredUser.findById(uid);

			Tutorial tutorial = Tutorial.findById(tutorialId);
			List<Request> pending = Request.find(
					"requesterID =? and entityId =?", uid, tutorialId).fetch();
			long replier = tutorial.creator.id;

			if (!(tutorial.contributorsList.contains(user)) // check if he is
															// not a contributor
					&& (pending.isEmpty()) // check if status is NOT Request
											// Pending
					&& !(tutorial.creator == user)) // check that the
													// requester is not the
													// creator
			{
				new Request(user.id, tutorialId, replier,
						"request to Contribute",
						"/Tutorials/tutorialPage?tutId=" + tutorialId).save();
				renderText("You have submitted Your Request");
			} else if ((tutorial.creator == user)) {
				renderText("You are the creator of this tutorial, you cannot do this action ");
			} else
				renderText("you either a contributor to this tutorial or having your request pending");
		} else {
			renderText("you are not logged-in please log in");
		}
	}

	// End ---> Omnia

	// START-----Haidy

	/**
	 * This method checks whether the user is contributor or creator of the
	 * tutorial in order to perform the edit and then render the tutorial in the
	 * EditTutorial page
	 * 
	 * @author Haidy
	 * @param tutorialId
	 */
	public static void editTutorial(long tutorialId) {
		if (session.get("RegisteredUserId") != null) {
			long userId = Long.parseLong(session.get("RegisteredUserId"));
			RegisteredUser user = RegisteredUser.findById(userId);
			models.Tutorial tutorial = models.Tutorial.findById(tutorialId);
			if (tutorial.getContributorsList().contains(user)
					|| user.id == tutorial.creator.id) {
				int version = tutorial.edits.size() - 1;
				render(tutorial, version);
			} else {
				renderText("Oops..You are not authorized to Edit this tutorial,Please make sure you are assigned to edit this tutorial");
			}
		} else {
			renderText("you should log in first");
		}
	}

	/**
	 * This method gets the user ID and the tutorial ID and renders the tutorial
	 * of this ID
	 * 
	 * @author Haidy
	 * @param tutorialId
	 *            ,versionId
	 */
	public static void contEditTutorial(long tutorialId, long versionId) {
		models.Tutorial tutorial = models.Tutorial.findById(tutorialId);
		models.editVersion version = models.editVersion.findById(versionId);
		render(tutorial, version);
	}

	/**
	 * This method gets the previous edit version and display it on the
	 * versionPage
	 * 
	 * @author Haidy
	 * @param tutorialId
	 *            ,version
	 */
	public static void versionPage(long tutorialId, long version) {
		models.editVersion tutorial = models.editVersion.findById(tutorialId);
		models.Tutorial edit = models.Tutorial.findById(tutorialId);
		if (version == -1) {
			if (edit.edits.size() - 2 < 0) {
				renderText("This is the last version");
			} else {
				int num = (int) edit.edits.size() - 1;
				editVersion version1 = editVersion.findById(edit.edits
						.get(num - 1).id);
				render(version1, tutorial, edit);
			}
		} else {
			editVersion version1 = editVersion.findById(version);
			List<editVersion> allVersions = edit.edits;
			render(version1, edit, allVersions, tutorial);
		}
	}

	/**
	 * This method allows the edit of the tutorial and also allwos the replace
	 * of it with old version of the tutorial
	 * 
	 * @author Haidy Essam
	 * @param : tutorialId,title,content,words,exp
	 */
	public static void updateChanges(
			long tutorialId,
			@Required(message = "You need to Enter the Title") String title,
			@Required(message = "You need to Enter the Content") String content,
			@Required(message = "You need to Enter the Related Words") String words,
			String Exp) {

		if (validation.hasErrors()) {
			params.flash();
			validation.keep();
			editTutorial(tutorialId);
		} else {
			models.Tutorial tutorial = models.Tutorial.findById(tutorialId);
			tutorial.setTitle(title);
			tutorial.setContent(content);
			tutorial.setStringofwords(words);
			tutorial.setExpLevel(Exp);
			tutorial.save();
			models.editVersion edit = new models.editVersion(tutorialId, title,
					content, words, Exp);
			edit.setTitle(title);
			edit.setContent(content);
			edit.setStringofwords(words);
			edit.setExpLevel(Exp);
			edit.save();
			tutorial.edits.add(edit);
			tutorial.save();
			Application.updates();
		}
	}

	/**
	 * This method display all the edit versions of the tutorial
	 * 
	 * @author Haidy
	 * @param tutorialId
	 */
	public static void allEditVersions(long tutorialId) {
		Tutorial tutorial = Tutorial.findById(tutorialId);
		List<editVersion> allVersions = tutorial.edits;
		render(allVersions, tutorial);
	}

	// END------Haidy

	/**
	 * this method updates the title of the related tutorial and relation by
	 * replacing the relation from the drop list
	 * 
	 * @author Yasmin G.
	 * @param tutID
	 * @param otherTitle
	 * @param type
	 */

	public static void updateRelation(long tutID, String otherTitle, String type) {
		models.Tutorial tutorial = models.Tutorial.findById(tutID);
		String tutorialTitle = tutorial.Title;
		Relation relation = Relation.find("TutorialTitle=?", tutorialTitle)
				.first();
		relation.setRelatedTutTitle(otherTitle);
		relation.setRelType(type);
		relation.save();
		Tutorials.tutorialPage(tutID);
	}

	/**
	 * This method checks if the user is a housekeeper to allow the relation to
	 * be edited. and display the relation of the tutorial and display all the
	 * tutorials in the DB to choose from.
	 * 
	 * @param tutId
	 *            : id of the tutorial
	 * @author Yasmin G.
	 */

	public static void editRelation(long tutId) {
		long uId = Long.parseLong(session.get("RegisteredUserId"));
		RegisteredUser user = RegisteredUser.findById(uId);
		if (user.isHousekeeper == true) {
			Tutorial currentTut = Tutorial.findById(tutId);
			String Title = currentTut.Title;
			List<Relation> relation = Relation.find("TutorialTitle=?", Title)
					.fetch();
			List<Tutorial> Tutorials = Tutorial.find("id!=?", tutId).fetch();
			if (!relation.isEmpty()) {
				render(relation, Tutorials, currentTut);
			} else {
				renderText("There are no created Relation yet..");
			}
		} else {
			renderText("You are not authorized to Edit this Relation");
		}
	}

	/**
	 * This method calls the method followTutorial in Model Tutorial and checks
	 * if the followed tutorial is in the followedtuts list, it renders text
	 * that the user is already following this tutorial, if not it renders text
	 * that the user has successfully followed this tutorial
	 * 
	 * @param tId
	 *            which is the id of the followed tutorial.
	 * @return rendered Text if the user is not logged in, if he's the creator,
	 *         if he's already following this tutorial and if he successfully
	 *         followed the tutorial
	 * 
	 * @author Marwa
	 * @author Omnia -Notification
	 */
	public static void followTut(long tId) {
		if (session.get("RegisteredUserId") != null) {
			long userId = Long.parseLong(session.get("RegisteredUserId"));
			Tutorial tutorial = Tutorial.findById(tId);
			RegisteredUser creator = tutorial.creator;
			long creatorId = creator.id;
			if (userId != creatorId) {
				boolean res = tutorial.followTutorial(userId, tId);
				if (res == true) {
					if (userId != creatorId)
						new Notification(userId, creatorId, tId, 5).save();
					renderText("You have successfully followed this Tutorial");
				} else {
					renderText("You Are already following this Tutorial");
				}
			} else {
				renderText("You can't Follow your own Tutorial :)");
			}
		} else {
			renderText("You must Log in first to follow a Tutorial!!");
		}
	}

	/**
	 * this method returns a list of followed tutorials it contains a condition
	 * were it checks first if it is the registered user who is viewing or
	 * others
	 * 
	 * @author Nada
	 * @param viewOthers
	 */

	public static void followedTutPage(long viewOthers) {
		long registeredUser = Long.parseLong(session.get("RegisteredUserId"));
		RegisteredUser user = RegisteredUser.findById(registeredUser);
		RegisteredUser otherUser = RegisteredUser.findById(viewOthers);
		if (user != otherUser) {
			List<Tutorial> followedTuts = otherUser
					.viewFollowedTutorials(otherUser.id);
			render(followedTuts);
		}

		List<Tutorial> followedTuts = user.viewFollowedTutorials(registeredUser);
		render(followedTuts);
	}

	/**
	 * This method calls the method addTutorialToFavorites in Model Tutorial and
	 * checks if the added tutorial is in the favorites list, it renders text
	 * that the user had already added this tutorial, if not it renders text
	 * that the user has successfully added this tutorial to favorites
	 * 
	 * @param tId
	 *            which is the id of the added tutorial.
	 * 
	 * @return rendered Text if the user is not logged in, if he's already added
	 *         this tutorial and if he successfully added the tutorial to
	 *         favorites
	 * 
	 * @author Marwa
	 */
	public static void addTutToFav(long tId) {
		if (session.get("RegisteredUserId") != null) {
			long userId = Long.parseLong(session.get("RegisteredUserId"));
			Tutorial tutorial = Tutorial.findById(tId);
			boolean result = tutorial.addTutorialToFavorites(userId, tId);
			if (result == true) {
				renderText("You have successfully added this Tutorial to Favorites");
			} else {
				renderText("This Tutorial is already in your Favorites List");
			}
		} else {
			renderText("You must Log in to do that action!!");
		}
	}

	/**
	 * This method calls the method viewFavoriteTutorials in Model Registered
	 * user and renders the list of favorites
	 * 
	 * @return List of favorite tutorials
	 * 
	 * @author Marwa
	 */
	public static void favoritesPage() {
		long fid = Long.parseLong(session.get("RegisteredUserId"));
		RegisteredUser user = RegisteredUser.findById(fid);
		List<Tutorial> favoriteTuts = user.viewFavoriteTutorials(fid);
		render(favoriteTuts);
	}

	/**
	 * This method will enable the initial and the registered users to browse
	 * tutorial topics through material level
	 * 
	 * @author Ghada Kades
	 */
	public static void browseMaterial() {

		List<Tutorial> tutorials = Tutorial.find("status=?", "publish").fetch();
		List<Tutorial> beginner = new ArrayList<Tutorial>();
		List<Tutorial> medium = new ArrayList<Tutorial>();
		List<Tutorial> expert = new ArrayList<Tutorial>();
		for (int j = 0; j < tutorials.size(); j++) {
			if (tutorials.get(j).ExpLevel.equals("Beginner")) {
				beginner.add(tutorials.get(j));
			} else if (tutorials.get(j).ExpLevel.equals("Medium")) {
				medium.add(tutorials.get(j));
			} else if (tutorials.get(j).ExpLevel.equals("Expert")) {
				expert.add(tutorials.get(j));
			}
		}

		render(tutorials, beginner, medium, expert);
	}

	/**
	 * This method will enable the initial and the registered users to browse
	 * tutorial topics through relations
	 * 
	 * @author shayma hesham
	 */

	public static void browsRelations() {
		List<Tutorial> tutorials = Tutorial.find("status=?", "draft").fetch();
		List<Relation> relation = Relation.findAll();
		List<Relation> similar = new ArrayList<Relation>();
		List<Relation> replace = new ArrayList<Relation>();
		List<Relation> requiredTo = new ArrayList<Relation>();
		List<Relation> requiredFor = new ArrayList<Relation>();
		List<Relation> partOf = new ArrayList<Relation>();
		for (int j = 0; j < relation.size(); j++) {
			if (relation.get(j).relType.equals("similar")) {
				similar.add(relation.get(j));
			} else if (relation.get(j).relType.equals("replace")) {
				replace.add(relation.get(j));
			} else if (relation.get(j).relType.equals("required to")) {
				requiredTo.add(relation.get(j));
			} else if (relation.get(j).relType.equals("required for")) {
				requiredFor.add(relation.get(j));
			} else if (relation.get(j).relType.equals("part of")) {
				partOf.add(relation.get(j));
			}
		}

		render(relation, similar, replace, requiredTo, requiredFor, partOf);
	}

	// }

	// RegisteredUser user = new RegisteredUser("moahmed", "mdfd@yzsh.com",
	// "1245");

	// long x = Long.parseLong("1");
	// models.Tutorial tut = new models.Tutorial("asdf", "fgfgfg", "fgfgfg",
	// "gdfg","fgfg", x, "red").save();
	/*
	 * // long userID = Long.parseLong(session.get("RegisteredUserId")); //
	 * models.RegisteredUser user = models.RegisteredUser.findById(userID); //
	 * long tt1 = Long.parseLong(session.get("tutId")); // models.Tutorial tuto
	 * = models.Tutorial.findById(tt1); // // if (user.isContributor ||
	 * user.isCreator && tuto.status == "publish") { // String str = tuto.Title
	 * + " >> "; // Stack s = tuto.relation; // // for (int i = 0; i < s.size();
	 * i++) { // str += s.pop().toString() + " , "; // } // // //
	 * s.relation.pop(); // // List<models.Tutorial> tutorials= // //
	 * models.Tutorial.em().createQuery(
	 * "SELECT Title, Topic, relation FROM Tutorial GROUP BY Topic;"
	 * ).getResultList(); // // String str= "dfsdfds"; // render(str); //
	 * Tutorial(); // } // }
	 * 
	 * if (user.isContributor || user.isCreator && tuto.status == "publish") {
	 * String str = tuto.Title + " >> "; Stack s = tuto.relation;
	 * 
	 * for (int i = 0; i < s.size(); i++) { str += s.pop().toString() + " , "; }
	 * 
	 * // s.relation.pop(); // List<models.Tutorial> tutorials= //
	 * models.Tutorial.em().createQuery(
	 * "SELECT Title, Topic, relation FROM Tutorial GROUP BY Topic;"
	 * ).getResultList(); // String str= "dfsdfds"; render(str); Tutorial(); }
	 */
	// end shayma

	// shayma hesham this method view the all the reviews which is made by the
	// credited user on my points
	// public static void viewReview(){
	//
	// long tutId = Long.parseLong(session.get("tutId")); //this line to get the
	// id of a tutorial by using session
	// List<models.Reviews> reviews =
	// models.Reviews.em().createQuery("SELECT review FROM Reviews where tutID="+tutId).getResultList();
	// // to get the review for a specefic tutrial from database
	//
	//
	// //List<Review> reviews=
	// Review.em().createQuery("SELECT review FROM Reviews").getResultList();
	//
	// render(reviews);
	// //String str = "ddddddddd"; this line to test
	// //render(str);
	//
	// Tutorial();
	// }

	/*
	 * public void publish() { String email = (session.get("email"));
	 * RegisteredUser ru = RegisteredUser.findById(email);
	 * 
	 * if (ru.isReviewer() == true ) {
	 * 
	 * } }
	 */
	/*
	 * // Marwa public static void Tutorial(long id) { session.put("TutorialID",
	 * id); // models.Tutorial u = models.Tutorial.findById(id); // String name
	 * = u.Title; // //String tutContent = u.content; // render(name); //
	 * //render(tutContent); List<models.Tutorial> tutorial =
	 * (List<models.Tutorial>) models.Tutorial
	 * .find("SELECT * FROM Tutorial WHERE Tutorial.id = TutorialID") .first();
	 * render(tutorial); }
	 */
	/*
	 * public static void Tutorials(long tutorialId) { List<models.Tutorial>
	 * tutorials = models.Tutorial.find( "tutorial.id = ?", tutorialId).fetch();
	 * render(tutorials); }
	 */

	/**
	 * This method allows people to see public comments
	 * 
	 * @param tutorialId
	 *            which is the id of the tutorial the user is accessing
	 * 
	 * @return the list of public comments and the tutorial id
	 * 
	 * @author Rana A. Zakaria
	 */

	public static void viewPublicComments(long tutorialId) {
		List<Comment> publicComments = Comment.find("tutId =? and isPrivate=?",
				tutorialId, false).fetch();
		long userId = Long.parseLong(session.get("RegisteredUserId"));
		RegisteredUser user = RegisteredUser.findById(userId);
		Tutorial tutorial = Tutorial.findById(tutorialId);

		boolean canDelete = (tutorial.contributorsList.contains(user))
				|| tutorial.creator.equals(user);
		render(publicComments, canDelete, tutorialId);
	}

	/**
	 * This method allows the registered users to post a public or private
	 * comment on tutorials
	 * 
	 * @param commentBody
	 *            which is the comment that the user enters in the html
	 * @param tutorialId
	 *            , which is the id of the tutorial the user is accessing
	 * @param choice
	 *            which is the choice whether it's public or private comment
	 * 
	 * @return a text of whether the comment has been posted or he didn't enter
	 *         a comment, or he's not a logged in user
	 * 
	 * @author Rana A. Zakaria
	 */

	public static void createComment(@Required String commentBody,
			long tutorialId, String choice) {

		if (session.get("RegisteredUserId") != null) {

			long userId = Long.parseLong(session.get("RegisteredUserId"));
			RegisteredUser user = RegisteredUser.findById(userId);
			Tutorial tutorial = Tutorial.findById(tutorialId);
			if (choice.equals("Public comment")) {
				if (commentBody.equals("")) {
					renderText("Oops, you didn't enter a comment");
				} else {
					new Comment(commentBody, tutorialId, user.id, false).save();
					if (userId != tutorial.creator.id)
						new Notification(userId, tutorial.creator.id,
								tutorialId, 2).save();
				}
			} else {
				if (commentBody.equals("")) {
					renderText("Oops, you didn't enter a comment");
				} else {
					if (choice.equals("Private comment")) {
						Comment privateComment = new Comment(commentBody,
								tutorialId, user.id, true).save();
						new Notification(userId, tutorial.creator.id,
								tutorialId, 2).save();
					}
				}
			}
			renderText("Your comment has been posted");
		}
		renderText("Sorry, but you're not a user");
	}

	/**
	 * This method allows the creator/contributors to view the private comments
	 * 
	 * @param tutorialId
	 *            which is the id of the tutorial the user is accessing.
	 * 
	 * @return the list of private comments and the tutorial id, or a text that
	 *         the user can't view the public comments
	 * @author Rana A. Zakaria
	 */

	public static void viewPrivateComments(long tutorialId) {
		if (session.get("RegisteredUserId") != null) {
			long userId = Long.parseLong(session.get("RegisteredUserId"));
			RegisteredUser user = RegisteredUser.findById(userId);
			Tutorial tutorial = Tutorial.findById(tutorialId);
			List<Comment> privateComments = Comment.find(
					"tutId =? and isPrivate=?", tutorialId, true).fetch();
			if (tutorial.contributorsList.contains(user)
					|| (tutorial.creator == user)) {
				render(privateComments, tutorialId);
			}
		}
		renderText("Sorry, but only the creator and contributors can view private comments");
	}

	/**
	 * This method render to the browse page
	 * 
	 * */
	public static void browseMain() {
		render();
	}

	/**
	 * This method passes the topics and the published tutorials to the
	 * browseTypes.html.
	 * 
	 * @author Dina.
	 **/
	public static void browseTypes() {
		try {
			List<Topic> topics = Topic.findAll();
			List<Tutorial> tutorials = Tutorial.find("status=?", "publish")
					.fetch();
			boolean empty = false;
			if (tutorials.isEmpty()) {
				empty = true;
			}
			boolean flag = false;
			long userId = Long.parseLong(session.get("RegisteredUserId"));
			RegisteredUser user = RegisteredUser.findById(userId);
			if (user != null) {
				flag = true;
			}
			render(topics, tutorials, flag, empty);
		} catch (Exception e) {
			List<Topic> topics = Topic.findAll();
			List<Tutorial> tutorials = Tutorial.find("status=?", "publish")
					.fetch();
			boolean empty = false;
			if (tutorials.isEmpty()) {
				empty = true;
			}
			boolean flag = false;
			render(topics, tutorials, flag, empty);
		}
	}

	// Ragab

	/**
	 * 
	 * i used this method to return the uploaded media files after the uploading
	 * of each file to show them in the relation page, and if the user wants to
	 * upload another media files he can do that and he will see all the media
	 * files he uploaded every time after finishing teh uploading process
	 * 
	 * @author Mohamed Ragab
	 * 
	 */
	public static List<Media> findUploads() {
		long ID = Long.parseLong(session.get("TutorialID"));

		List<Media> uploads;

		uploads = Media.find("tutId=? ", ID).fetch();

		return uploads;
	}

	/**
	 * 
	 * i used this method to return the uploaded media files related to each
	 * tutorial to show them in the tutorialPage.html
	 * 
	 * @author Mohamed Ragab
	 * 
	 * @param long ID
	 */

	public static List<Media> findUploads(long ID) {

		List<Media> uploads;

		uploads = Media.find("tutId=? ", ID).fetch();

		return uploads;
	}

	/**
	 * 
	 * i used this method to added the media files and upload them to the system
	 * and save them in the database and the user can decide to play the media
	 * file manually or automatically
	 * 
	 * @author Mohamed Ragab
	 * 
	 * @param Media
	 *            media, String type, int autoplay
	 */
	public static void addFile(Media media, String type, int autoplay) {

		long tt = Long.parseLong(session.get("TutorialID"));
		Tutorial tut = Tutorial.findById(tt);

		media.tutID = tt;
		media.tut = tut;

		if (autoplay == 1)
			media.autoplay = true;
		else
			media.autoplay = false;
		media.type = type;

		long uid = Long.parseLong(session.get("RegisteredUserId"));
		RegisteredUser u = RegisteredUser.findById(uid);

		LogRecord.createLog("Adding new Media", u);
		media.save();
		relation(tut.id);

	}

	// end of Ragab

	/**
	 * This method allows the users to send a request to the contributors and
	 * the creator to edit a request.
	 * 
	 * @param tutorialId
	 *            which is the tutorial id that the user is accessing
	 * 
	 * @param oldContent
	 *            which is the content of the tutorial the user is accessing
	 * 
	 * @param editBody
	 *            which is the edit body that the user has entered.
	 * 
	 * @return a text that notifies the user whether he's allowes to send a
	 *         request or not, or whether he've sent it beofre or not, or
	 *         whether he has entered any changes or not, or that the request
	 *         has been successfully sent
	 * 
	 * @author Rana A. Zakaria
	 */

	public static void requestToEdit(long tutorialId, String oldContent,
			String editBody) {
		if (session.get("RegisteredUserId") != null) {
			long uid = Long.parseLong(session.get("RegisteredUserId"));
			RegisteredUser user = RegisteredUser.findById(uid);
			Tutorial tutorial = Tutorial.findById(tutorialId);
			long replier = tutorial.creator.id;

			List<EditRequest> sameRequester = EditRequest
					.find("tutorialId=? and requesterId =? and isApproved =? and isChecked =?",
							tutorialId, uid, false, false).fetch();

			for (int i = 0; i < sameRequester.size(); i++) {

				EditRequest request = sameRequester.get(i);
				String compare = request.edit;
				if (editBody.equals(compare))
					renderText("Sorry, but you've already sent this request");

			}

			if (editBody.equals(oldContent)) {
				renderText("Sorry, but it seems you haven't entered any changes.");
			} else if (editBody.equals("")) {
				renderText("Oops, you didn't enter any text");
			} else {

				new EditRequest(editBody, tutorial.id, user.id, replier, false,
						false).save();
				renderText("Your request has been successfully sent :)");
			}
		}
	}

	/**
	 * This method renders the tutorial the user is accessing
	 * 
	 * @param id
	 *            which is the id that it takes from the html.
	 * 
	 * @return the tutorial that the user is accessing or a text whether he's
	 *         the creator or the contributor, or whether he can't even access
	 *         the page
	 * 
	 * @author Rana A. Zakaria
	 */

	public static void editRequest(long id) {
		if (session.get("RegisteredUserId") != null) {
			long uid = Long.parseLong(session.get("RegisteredUserId"));
			RegisteredUser user = RegisteredUser.findById(uid);
			models.Tutorial temptutorialTutorial = models.Tutorial.findById(id);
			if (user == temptutorialTutorial.creator) {
				renderText("Oops, you're already the creator, you can't request to edit");
			} else if (user == temptutorialTutorial.contributorsList) {
				renderText("Oops, you're already a contributor in this tutorial");
			} else {

				render(temptutorialTutorial);
			}
		}
		renderText("Sorry, but you're not a user");
	}

	/**
	 * This method allows users to rate a tutorial
	 * 
	 * @param tutorialId
	 *            which is the id of the tutorial the user is accessing
	 * 
	 * @param rate
	 *            which is the rate he enters.
	 * 
	 * @return a text that tells the user whether he has already rated the
	 *         tutorial before, or he's not a user, or that he has succesfully
	 *         rated the tutorial
	 * 
	 * @author Rana A. Zakaria
	 */

	public static void rateTutorial(long tutorialId, int rate) {
		if (session.get("RegisteredUserId") != null) {
			{
				long userId = Long.parseLong(session.get("RegisteredUserId"));
				RegisteredUser user = RegisteredUser.findById(userId);
				Tutorial tut = Tutorial.findById(tutorialId);
				if (!(user.rateList.contains(tut)))

				{
					tut.rates++;
					tut.averageRate = (tut.averageRate + rate) / tut.rates;
					tut.save();
					user.rateList.add(tut);
					user.save();
					if (userId != tut.creator.id)
						new Notification(userId, tut.creator.id, tut.id, 4)
								.save();
					renderText("Thank you for rating this tutorial :)");
				}
			}
			renderText("Oops..it seems that you have rated this tutorial before!");
		}
		renderText("Sorry, but you're not a user");
	}

	/**
	 * This methos allows the creator/contributors to view the edit requests
	 * 
	 * @param tutorialId
	 *            which is the id of the tutorial the user is accessing.
	 * 
	 * @return a list of the requests and the tutorial id, or a text that he
	 *         can't view the requests.
	 * 
	 * @author Rana A. Zakaria
	 */
	public static void viewEditRequests(long tutorialId) {
		if (session.get("RegisteredUserId") != null) {
			long userId = Long.parseLong(session.get("RegisteredUserId"));
			RegisteredUser user = RegisteredUser.findById(userId);
			Tutorial tutorial = Tutorial.findById(tutorialId);
			List<EditRequest> requests = EditRequest.find(
					"tutorialId =? and isApproved=? and isChecked=?",
					tutorialId, false, false).fetch();
			if (tutorial.contributorsList.contains(user)
					|| (tutorial.creator == user)) {
				render(requests, tutorialId);
			} else
				renderText("Sorry, but only the creator and contributors can view the requests to edit a tutorial!!");

		}

	}

}
